package pinkblob.event;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.apache.log4j.Logger;

import pinkblob.entity.ProjectInformation;
import pinkblob.log.Log;

public abstract class AProjectInformationHandler {

	private static EntityManagerFactory emf = null;
	protected static EntityManager em = null;

	protected static Logger log = new Log()
			.getLogger(AProjectInformationHandler.class);

	protected ProjectInformation pi = null;
	protected Integer pid = null;

	// private static Long CRLastDesigner = 0l;

	public Integer getPid() {
		return this.pid;
	}

	protected void setPid(Integer pid) {
		this.pid = pid;
	}
	
	public Integer getIterationsBase() {
		return ProjectInformation.ITERATIONSBASE;
	}

	public AProjectInformationHandler() {
		if (emf == null)
			emf = Persistence.createEntityManagerFactory("PinkBlob2");
		if (em == null)
			em = emf.createEntityManager();
		System.out.println("Successfully constructed PIH: " + this.toString());
	}

	// public void setCRLastDesignerID(Long id) {
	// CRLastDesigner = id;
	// }

	@SuppressWarnings("unchecked")
	public void setProjectInformation(Map data) {
		this.pid = Integer.parseInt((String) data.get("ProjectID"));
		getProjectInformation();
		em.getTransaction().begin();
		for (Object key : data.keySet()) {
			log.debug("Updating: " + (String) key + " with value " + data.get(key));
			if (data.get(key) != null) {
				if (key.equals("II_AdmonitionMailCommnet"))
					pi.setII_AdmonitionMailComment((String) data.get(key));
				else if (key.equals("Price"))
					pi.setPrice((Float) data.get(key));
				else if (key.equals("II_BillMailComment"))
					pi.setII_BillMailComment((String) data.get(key));
				else if (key.equals("Pid"))
					pi.setPid((Integer) data.get(key));
				else if (key.equals("Comment"))
					pi.setComment((String) data.get(key));
				else if (key.equals("ProjectID"))
					pi.setProjectID((String) data.get(key));
				else if (key.equals("TextDesign"))
					pi.setTextDesign((Boolean) data.get(key));
				else if (key.equals("GraphicDesign"))
					pi.setGraphicDesign((Boolean) data.get(key));
				else if (key.equals("FD_DesignAccepted"))
					pi.setFD_DesignAccepted((Boolean) data.get(key));
				else if (key.equals("Status"))
					pi.setStatus((Integer) data.get(key));
				else if (key.equals("CR_LastDesignerID"))
					pi.setCR_LastDesignerID((Long) data.get(key));
				else if (key.equals("CR_InformationNeed"))
					pi.setCR_InformationNeed((Boolean) data.get(key));
				else if (key.equals("HighPriority"))
					pi.setHighPriority((Boolean) data.get(key));
				else if (key.equals("D_Texts"))
					pi.setD_Texts((String) data.get(key));
				else if (key.equals("D_Graphics"))
					pi.setD_Graphics((String) data.get(key));
				else if (key.equals("DesignRequirements"))
					pi.setDesignRequirements((String) data.get(key));
				else if (key.equals("D_Draft"))
					pi.setD_Draft((String) data.get(key));
				else if (key.equals("Design"))
					pi.setDesign((String) data.get(key));
				else if (key.equals("Agreement"))
					pi.setAgreement((String) data.get(key));
				else if (key.equals("EvaluationDetails"))
					pi.setEvaluationDetails((String) data.get(key));
				else if (key.equals("EPMA_AgreementUpdateNeeded"))
					pi.setEPMA_AgreementUpdateNeeded((Boolean) data.get(key));
				else if (key.equals("EPMA_LastSalesClerk"))
					pi.setEPMA_LastSalesClerk((Long) data.get(key));
				else if (key.equals("CR_InformationRequest"))
					pi.setCR_InformationRequest((String) data.get(key));
				else if (key.equals("Deadline"))
					pi.setDeadline((Date) data.get(key));
				else if (key.equals("D_DraftAccepted"))
					pi.setD_DraftAccepted((Boolean) data.get(key));
				else if (key.equals("FD_IDQuality"))
					pi.setFD_IDQuality((Long) data.get(key));
				else if (key.equals("FD_GraphicsDesigner"))
					pi.setFD_GraphicsDesigner((Long) data.get(key));
				else if (key.equals("FD_Texter"))
					pi.setFD_Texter((Long) data.get(key));
				else if (key.equals("FD_SelectedFinalizer"))
					pi.setFD_SelectedFinalizer((Long) data.get(key));
				else if (key.equals("Iterations"))
					pi.setIterations((Integer) data.get(key));
				else if (key.equals("Bill"))
					pi.setBill((String) data.get(key));
				else if (key.equals("II_BillCreated"))
					pi.setII_BillCreated((Boolean) data.get(key));
				else if (key.equals("II_AdmonitionCounter"))
					pi.setII_AdmonitionCounter((Integer) data.get(key));
				else if (key.equals("II_LastAccountingClerk"))
					pi.setII_LastAccountingClerk((Long) data.get(key));
				else if (key.equals("Agreement_State"))
					pi.setAgreement_State((String) data.get(key));
				else if (key.equals("Agreement_State_Description"))
					pi.setAgreement_State_Description((String) data.get(key));
				else if (key.equals("CostCalc"))
					pi.setCostCalc((Float) data.get(key));
				else if (key.equals("D_DraftComment"))
					pi.setD_DraftComment((String) data.get(key));
				else if (key.equals("Iterations")) 
					pi.setIterations((Integer) data.get(key));
				else if (key.equals("II_AdmonitionMailComment")) 
					pi.setII_AdmonitionMailComment((String) data.get(key));
				else log.warn("Unknown Key, FIX THIS IN PROJECT INFORMATION HANDLER: "+(String) key);
			}
			// overwrite LastDesigner
			// if (!CRLastDesigner.equals(0l))
			// pi.setCR_LastDesignerID(CRLastDesigner);

		}
		em.getTransaction().commit();
	}

	public Map<String, Object> getProjectInformationMap(int pid) {
		log.debug("setting pid to "+pid+"! Calling global method afterwards.");
		this.setPid(pid);
		return this.getProjectInformationMap();
	}

	protected ProjectInformation getProjectInformation() {
		log.debug("retrieving ProjectInformation Entity from Database - pid: "+pid);
		em.getTransaction().begin();
		Query q = em
				.createQuery("select pi from ProjectInformation pi where pi.Pid = :pid");
		q.setParameter("pid", pid);
		try {
			pi = (ProjectInformation) q.getSingleResult();
		} catch (NoResultException ex) {
			pi = new ProjectInformation();
			pi.setPid(pid);
			em.persist(pi);

		}
		em.getTransaction().commit();
		return pi;
	}
	
	@SuppressWarnings("unchecked")
	public Map<String, Object> getProjectInformationMap() {
		log.debug("retrieving map - pid: "+pid);
		Map<String, Object> result = new HashMap<String, Object>();
		getProjectInformation();
		log.debug("transforming Object to the Map of the structured data type");
				// TODO: Here we have to map all information from the structured data
		// type
		// result.put("Pid",pi.getPid());
		// result.put("Comment",pi.getComment());
		result
				.put("II_AdmonitionMailComment", pi
						.getII_AdmonitionMailComment());
		result.put("II_BillMailComment", pi.getII_BillMailComment());
		result.put("Price", pi.getPrice());
		result.put("ProjectID", pi.getProjectID());
		result.put("TextDesign", pi.isTextDesign());
		result.put("GraphicDesign", pi.isGraphicDesign());
		result.put("FD_DesignAccepted", pi.isFD_DesignAccepted());
		result.put("Status", pi.getStatus());
		result.put("CR_LastDesignerID", pi.getCR_LastDesignerID());
		result.put("CR_InformationNeed", pi.isCR_InformationNeed());
		result.put("HighPriority", pi.isHighPriority());
		result.put("D_Texts", pi.getD_Texts());
		result.put("D_Graphics", pi.getD_Graphics());
		result.put("DesignRequirements", pi.getDesignRequirements());
		result.put("D_Draft", pi.getD_Draft());
		result.put("Design", pi.getDesign());
		result.put("Agreement", pi.getAgreement());
		result.put("EvaluationDetails", pi.getEvaluationDetails());
		result.put("EPMA_AgreementUpdateNeeded", pi
				.isEPMA_AgreementUpdateNeeded());
		result.put("EPMA_LastSalesClerk", pi.getEPMA_LastSalesClerk());
		result.put("CR_InformationRequest", pi.getCR_InformationRequest());
		result.put("Deadline", pi.getDeadline());
		result.put("D_DraftAccepted", pi.getD_DraftAccepted());
		result.put("FD_IDQuality", pi.getFD_IDQuality());
		result.put("FD_GraphicsDesigner", pi.getFD_GraphicsDesigner());
		result.put("FD_Texter", pi.getFD_Texter());
		result.put("FD_SelectedFinalizer", pi.getFD_SelectedFinalizer());
		result.put("Iterations", pi.getIterations());
		result.put("Bill", pi.getBill());
		result.put("II_BillCreated", pi.isII_BillCreated());
		result.put("II_AdmonitionCounter", pi.getII_AdmonitionCounter());
		result.put("II_LastAccountingClerk", pi.getII_LastAccountingClerk());
		result.put("Agreement_State", pi.getAgreement_State());
		result.put("Agreement_State_Description", pi
				.getAgreement_State_Description());
		result.put("CostCalc", pi.getCostCalc());
		result.put("D_DraftComment", pi.getD_DraftComment());
		//em.getTransaction().commit();
		return result;
	}

	public ProjectInformation getProjectInformation(int id) throws Exception {
		log.debug("retrieving Project Information Object for pid: "+id);
		em.getTransaction().begin();
		Query q = em
				.createQuery("select pi from ProjectInformation pi where pi.Pid = :pid");
		q.setParameter("pid", id);
		try {
			pi = (ProjectInformation) q.getSingleResult();
		} catch (NoResultException ex) {
			pi = new ProjectInformation();
			pi.setPid(id);
			em.persist(pi);
		}
		em.getTransaction().commit();

		return pi;

	}
	
	public void abortProject(int id) {
		try {
			ProjectInformation pi = getProjectInformation(id);
			pi.setStatus(14);
			em.getTransaction().begin();
			em.merge(pi);
			em.persist(pi);
			em.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	public List<ProjectInformation> getAllProjectInformation(boolean includeFinished) {
		ArrayList<ProjectInformation> result = new ArrayList<ProjectInformation>();
		
		em.getTransaction().begin();
		
		String condition = "";
		if (!includeFinished) {
			condition = "where not (pi.Status=10 or pi.Status=12 or pi.Status=14 or pi.Status=15)";
		}
		
		Query q = em.createQuery("select pi from ProjectInformation pi " + condition);
		
		List queryresult = q.getResultList();
		
		for (Object o : queryresult) {
			result.add((ProjectInformation)o);
		}
		
		em.getTransaction().commit();
		
		return result;
	}

}
